/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <stdexcept>
#include <QFileInfo>
#include <QDir>
#include <QFile>
#include "log.h"
#include "paths.h"
#include "templatethreadbuilder.h"
#include "ui/templatethreadbuilderconfig.h"

namespace Wishmaster
{
	TemplateThreadBuilder::TemplateThreadBuilder() : 
		ThreadBuilder(),
		m_id(0)
	{
	}

	TemplateThreadBuilder::~TemplateThreadBuilder()
	{
	}

	bool TemplateThreadBuilder::loadTemplate(const QString& filename)
	{
		log(llDebug, "Loading template: %s", qPrintable(filename));
		QFileInfo info(filename);
		QMap<QString, QString> files = loadMap(filename);
		if(files.isEmpty())
		{
			log(llError, "Unable to load template: %s", qPrintable(filename));
			return false;
		}
		QMapIterator<QString, QString> it(files);
		while(it.hasNext())
		{
			it.next();
			QByteArray arr = load(info.absolutePath() + QDir::separator() + it.value());
			if(it.key() == "head")
				m_head = arr;
			else if(it.key() == "post")
				m_post = arr;
			else if(it.key() == "tail")
				m_tail = arr;
			else if(it.key() == "image")
				m_image = arr;
			else if(it.key() == "include")
				m_includes.append(it.value());
		}
		return true;
	}

	QMap<QString, QString> TemplateThreadBuilder::loadMap(const QString& filename)
	{
		QFile f(filename);
		QMap<QString, QString> files;
		if(!f.open(QIODevice::ReadOnly))
			return files;
		while(!f.atEnd())
		{
			QString line = f.readLine().trimmed();
			QStringList keyval = line.split('=');
			if(keyval.size() == 2)
			{
				files.insert(keyval.at(0).trimmed(), keyval.at(1).trimmed());
			}
		}
		f.close();
		return files;
	}

	void TemplateThreadBuilder::start(const QString& title)
	{
		loadTemplate(m_templateFilename);
		m_result.append(m_head);
		m_result.replace("${TITLE}", title.toUtf8());
	}

	void TemplateThreadBuilder::emitPost(PostPtr post)
	{
		if(!m_id)
			m_id = post->id().postId();
		QByteArray chunk = m_post;
		chunk.replace(QByteArray("${POST_ID}"), QByteArray::number((uint)post->id().postId()));
		chunk.replace(QByteArray("${TOPIC}"), post->topic().toUtf8());
		chunk.replace(QByteArray("${TEXT}"), post->text().toUtf8());
		chunk.replace(QByteArray("${ATTACHMENTS}"), addAttachments(post));
		m_result.append(chunk);
	}

	// Warning, side effects
	QByteArray TemplateThreadBuilder::addAttachments(PostPtr post)
	{
		QByteArray result;
		for(int attachIndex = 0; attachIndex < post->attachmentCount(); attachIndex++)
		{
			AttachmentPtr attach = post->attachment(attachIndex);
			QImage thumb = attach->thumbnail();
			QString thumblink = makeThumbPath(post, attachIndex);
			QString filelink = makeFilePath(post, attachIndex);
			QString link = QString("<a href=\"%1\"><img src=\"%2\" class=\"thumb\"></a>").arg(filelink).arg(thumblink);
			m_images.insert(thumblink, thumb);
			if(attach->type().startsWith("image"))
			{
				QImage pic = attach->image();
				if(pic.isNull())
					pic = thumb;
				m_images.insert(filelink, pic);
			}
			QByteArray thisfile = m_image;
			thisfile.replace("${THUMBLINK}", link.toUtf8());
			result += thisfile;
		}
		return result;
	}

	QString TemplateThreadBuilder::makeFilePath(PostPtr post, int index)
	{
		QString path;
		path.append("thread");
		path.append(QString::number(m_id));
		path.append(QDir::separator());
		path.append(post->attachment(index)->filename());
		return path;
	}

	QString TemplateThreadBuilder::makeThumbPath(PostPtr post, int index)
	{
		QString path;
		path.append("thread");
		path.append(QString::number(m_id));
		path.append(QDir::separator());
		path.append("thumb");
		path.append(QString::number(index));
		path.append(QString::number(post->id().postId()));
		path.append(".jpg"); // FIXME format hardcoded
		return path;
	}

	void TemplateThreadBuilder::end()
	{
		m_result.append(m_tail);
	}

	bool TemplateThreadBuilder::save(const QString& path)
	{
		QString finalpath = path;
		if(!path.endsWith(".html"))
			finalpath.append(".html");
			
		QFileInfo info(finalpath);
		QFile f(finalpath);
		if(!f.open(QIODevice::WriteOnly))
			return false;
		f.write(m_result);
		f.close();

		QDir imageDir(info.absolutePath() + QDir::separator() + QString("thread") + QString::number(m_id));
		if(!imageDir.exists("."))
			imageDir.mkpath(".");

		QMapIterator<QString, QImage> it(m_images);
		while(it.hasNext())
		{
			it.next();
			it.value().save(info.absolutePath() + QDir::separator() + it.key());
		}
		foreach(const QString& inclusion, m_includes)
		{
			QFileInfo srcinfo(m_templateFilename);
			QFile::copy(srcinfo.absolutePath() + QDir::separator() + inclusion, info.absolutePath() + QDir::separator() + inclusion);
		}

		return true;
	}

	bool TemplateThreadBuilder::singleFile()
	{
		return false;
	}
	
	QString TemplateThreadBuilder::id()
	{
		return "html";
	}

	QString TemplateThreadBuilder::text()
	{
		return "html";
	}

	QByteArray TemplateThreadBuilder::load(const QString& filename)
	{
		QFile f(filename);
		if(!f.open(QIODevice::ReadOnly))
			throw std::runtime_error("Unable to open template file");
		return f.readAll();
	}

	QString TemplateThreadBuilder::filter()
	{
		return "HTML (*.html)";
	}

	QWidget* TemplateThreadBuilder::createConfigWidget()
	{
		return new TemplateThreadBuilderConfig();
	}

	bool TemplateThreadBuilder::applyConfig(QWidget* cfgWidget)
	{
		TemplateThreadBuilderConfig* config = qobject_cast<TemplateThreadBuilderConfig*>(cfgWidget);
		if(!config)
			return false;
		m_templateFilename = DefaultPath::templates() + QDir::separator() + config->templateId() + ".template";
		return true;
	}

	ThreadBuilderPtr TemplateThreadBuilder::clone()
	{
		return ThreadBuilderPtr(new TemplateThreadBuilder());
	}
}

